package com.beyondsoft.dtc.mobile.automation.base;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.beyondsoft.dtc.mobile.automation.impl.compatibility.CompatibilityTestExecutor;
import com.beyondsoft.dtc.mobile.automation.model.ApkFile;
import com.beyondsoft.dtc.mobile.automation.model.Device;
import com.beyondsoft.dtc.mobile.automation.model.Task;
import com.beyondsoft.dtc.mobile.automation.util.ShellUtil;
import com.beyondsoft.dtc.mobile.automation.util.StringUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

/**
 * Created by Robin on 3/11/2016.
 */
public class BaseController {
	private final static Logger logger = LoggerFactory
			.getLogger(BaseController.class);
	private final AtomicInteger concurrentCount = new AtomicInteger();
	private String rootPath;
	private Object deviceSerailNum;

	public static String API_URL = "";
	public static String STORAGE_URL = "";

	private static void printEnvironmentInfo() {
		String sb = ">>>>>>>>>>>>>>>> System Environments Info >>>>>>>>>>>>>>>>>\n"
				+ "os.name:["
				+ System.getProperty("os.name")
				+ "]\n"
				+ "os.arch:["
				+ System.getProperty("os.arch")
				+ "]\n"
				+ "os.version:["
				+ System.getProperty("os.version")
				+ "]\n"
				+ "file.separator:["
				+ System.getProperty("file.separator")
				+ "]\n"
				+ "path.separator:["
				+ System.getProperty("path.separator")
				+ "]\n"
				+ "line.separator:["
				+ System.getProperty("line.separator")
				+ "]\n"
				+ "user.name:["
				+ System.getProperty("user.name")
				+ "]\n"
				+ "user.home:["
				+ System.getProperty("user.home")
				+ "]\n"
				+ "user.dir:["
				+ System.getProperty("user.dir")
				+ "]\n"
				+ "java.version:["
				+ System.getProperty("java.version")
				+ "]\n"
				+ "java.vendor:["
				+ System.getProperty("java.vendor")
				+ "]\n"
				+ "java.vendor.url:["
				+ System.getProperty("java.vendor.url")
				+ "]\n"
				+ "java.home:["
				+ System.getProperty("java.home")
				+ "]\n"
				+ "java.vm.specification.version:["
				+ System.getProperty("java.vm.specification.version")
				+ "]\n"
				+ "java.class.version:["
				+ System.getProperty("java.class.version")
				+ "]\n"
				+ "java.class.path:["
				+ System.getProperty("java.class.path")
				+ "]\n"
				+ "java.library.path:["
				+ System.getProperty("java.library.path")
				+ "]\n"
				+ "java.io.tmpdir:["
				+ System.getProperty("java.io.tmpdir")
				+ "]\n"
				+ "java.compiler:["
				+ System.getProperty("java.compiler")
				+ "]\n"
				+ "java.ext.dirs:["
				+ System.getProperty("java.ext.dirs")
				+ "]\n"
				+ "API_URL:["
				+ System.getProperty("API_URL")
				+ "]\n"
				+ "API_COMPATIBILITY_REPORT_URL:["
				+ System.getProperty("API_COMPATIBILITY_REPORT_URL")
				+ "]\n"
				+ "API_KEYSTORE:[" + System.getProperty("API_KEYSTORE") + "]\n";
		logger.info(sb);
	}

	private static void printConfigurationInfo() {
		logger.info(">>>>>>>>>>>>>>>> Application Configuration Info >>>>>>>>>>>>>>>>>\n");
		logger.info(GlobalConfig.getInstance().toString());
	}

	private static boolean checkSystemEnv() {
		logger.info(">>>>>>>>>>>>>>>> Required System Commands Check >>>>>>>>>>>>>>>>>\n");
		boolean ret = true;

		String[] command = new String[] { "which", GlobalConstants.ADB_COMMAND };
		ShellUtil.CommandResult commandResult = ShellUtil.execCommand(command);
		if (!commandResult.isCommandSucceeded()) {
			ret = false;
		}
		logger.info("\n>>>>> {}", commandResult);

		command = new String[] { "which", GlobalConstants.AAPT_COMMAND };
		commandResult = ShellUtil.execCommand(command);
		if (!commandResult.isCommandSucceeded()) {
			ret = false;
		}
		logger.info("\n>>>>> {}", commandResult);

		command = new String[] { "which", "zip" };
		commandResult = ShellUtil.execCommand(command);
		if (!commandResult.isCommandSucceeded()) {
			ret = false;
		}
		logger.info("\n>>>>> {}", commandResult);

		command = new String[] { "which", "unzip" };
		commandResult = ShellUtil.execCommand(command);
		if (!commandResult.isCommandSucceeded()) {
			ret = false;
		}
		logger.info("\n>>>>> {}", commandResult);
		command = new String[] { "which", "awk" };
		commandResult = ShellUtil.execCommand(command);
		if (!commandResult.isCommandSucceeded()) {
			ret = false;
		}
		logger.info("\n>>>>> {}", commandResult);
		command = new String[] { "which", "perl" };
		commandResult = ShellUtil.execCommand(command);
		if (!commandResult.isCommandSucceeded()) {
			ret = false;
		}
		logger.info("\n>>>>> {}", commandResult);

		return ret;
	}

	public static void main(String[] args) throws Exception {

		printEnvironmentInfo();
		printConfigurationInfo();
		if (!checkSystemEnv()) {
			logger.error(">>> Required system commands check failed, will quit...>>>\n");
			return;
		}
		if (args != null && args.length >= 2) {
			String command = args[0];
			String parameters = args[1];

			if (GlobalConstants.TaskType.TASK_BACKUP.getTaskName()
					.equalsIgnoreCase(command)
					|| GlobalConstants.TaskType.TASK_RESTORE.getTaskName()
							.equalsIgnoreCase(command)) {
//				new BaseController().startBackUpOrRestore(command, parameters);
			} else if (GlobalConstants.TaskType.TASK_COMPATIBILITY
					.getTaskName().equalsIgnoreCase(command)) {
				new BaseController().startCompatibilityTest(parameters);
			} else if (GlobalConstants.TaskType.TASK_CALABASH.getTaskName()
					.equalsIgnoreCase(command)) {
//				new BaseController().startCalabashTest(parameters);
			} else if (GlobalConstants.TaskType.TASK_LETTUCE.getTaskName()
					.equalsIgnoreCase(command)) {
//				new BaseController().startLettuceTest(parameters);
			} else {
				throw new Exception("Unknown parameter !");
			}
		} else {
			throw new Exception(
					"Param is empty or Param's length less than 2 !");
		}
	}

	/**
	 * parse apk file, initialize application's package name, lable, launch
	 * activity, etc.
	 *
	 * @param apkFilePath
	 *            where apk file can be read.
	 * @return ApkFile
	 * @throws BaseException
	 *             customized exceptions
	 */
	private static ApkFile parseApkFile(String apkFilePath)
			throws BaseException {

		ApkFile apkFile = new ApkFile();
		String[] dumpCommand = { GlobalConstants.AAPT_COMMAND, "dump",
				"badging", apkFilePath };
		ShellUtil.CommandResult commandResult = ShellUtil
				.execCommand(dumpCommand);
		if (!commandResult.isCommandSucceeded()) {
			logger.info("parse apk file error!");
			return apkFile;
		}

		try {
			String[] results = commandResult.getResultMsg().split(
					GlobalConstants.SYMBOL_CRLF);
			for (String line : results) {
				if (StringUtil.isEmpty(line)) {
					continue;
				}

				line = line.trim();
				if (line.startsWith(GlobalConstants.KEY_PACKAGE_PREFIX)) {
					String[] pkgInfos = line
							.split(GlobalConstants.SYMBOL_SPACE);
					for (String pkgInfo : pkgInfos) {
						if (StringUtil.isEmpty(pkgInfo)) {
							continue;
						}

						if (pkgInfo
								.startsWith(GlobalConstants.KEY_PACKAGE_NAME)) {
							apkFile.setPackageName(pkgInfo
									.replace(GlobalConstants.KEY_PACKAGE_NAME,
											"")
									.replace(GlobalConstants.SYMBOL_QUOTE, "")
									.trim());
						} else if (pkgInfo
								.startsWith(GlobalConstants.KEY_VERSION_CODE)) {
							apkFile.setVersionCode(pkgInfo
									.replace(GlobalConstants.KEY_VERSION_CODE,
											"")
									.replace(GlobalConstants.SYMBOL_QUOTE, "")
									.trim());
						} else if (pkgInfo
								.startsWith(GlobalConstants.KEY_VERSION_NAME)) {
							apkFile.setVersionName(pkgInfo
									.replace(GlobalConstants.KEY_VERSION_NAME,
											"")
									.replace(GlobalConstants.SYMBOL_QUOTE, "")
									.trim());
						} else if (pkgInfo
								.startsWith(GlobalConstants.KEY_PLATFORM_BUILD_VERSION_NAME)) {
							apkFile.setPlatformBuildVersionName(pkgInfo
									.replace(
											GlobalConstants.KEY_PLATFORM_BUILD_VERSION_NAME,
											"")
									.replace(GlobalConstants.SYMBOL_QUOTE, "")
									.trim());
						}
					}
				} else if (line.startsWith(GlobalConstants.KEY_SDK_VERSION)) {
					// sdkVersion:'14'
					apkFile.setSdkVersion(line
							.replace(GlobalConstants.KEY_SDK_VERSION, "")
							.replace(GlobalConstants.SYMBOL_QUOTE, "").trim());
				} else if (line
						.startsWith(GlobalConstants.KEY_APPLICATION_PREFIX)) {
					String[] appInfos = line
							.split(GlobalConstants.SYMBOL_SPACE);
					for (String appInfo : appInfos) {
						if (StringUtil.isEmpty(appInfo)) {
							continue;
						}

						if (appInfo.startsWith(GlobalConstants.KEY_LABEL)) {
							apkFile.setName(appInfo
									.replace(GlobalConstants.KEY_LABEL, "")
									.replace(GlobalConstants.SYMBOL_QUOTE, "")
									.trim());
						} else if (appInfo.startsWith(GlobalConstants.KEY_ICON)) {
							apkFile.setIcon(appInfo
									.replace(GlobalConstants.KEY_ICON, "")
									.replace(GlobalConstants.SYMBOL_QUOTE, "")
									.trim());
						}
					}
				} else if (line.startsWith(GlobalConstants.KEY_ACTIVITY_PREFIX)) {
					String[] activityInfos = line
							.split(GlobalConstants.SYMBOL_SPACE);
					for (String activityInfo : activityInfos) {
						if (StringUtil.isEmpty(activityInfo)) {
							continue;
						}

						if (activityInfo
								.startsWith(GlobalConstants.KEY_LAUNCHABLE_ACTIVITY)) {
							// 有可能有多个，只取第一个（否则就可能启动失败）
							if (apkFile.getActivityName() == null
									|| apkFile.getActivityName().trim()
											.length() == 0) {
								apkFile.setActivityName(activityInfo
										.replace(
												GlobalConstants.KEY_LAUNCHABLE_ACTIVITY,
												"")
										.replace(GlobalConstants.SYMBOL_QUOTE,
												"").trim());
							}

						}
					}
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		
		if (StringUtil.isEmpty(apkFile.getActivityName()) || apkFile.getActivityName() == null) {
			String[] nameCommand = { GlobalConstants.AAPT_COMMAND, "dump",
	                    "xmltree", apkFilePath, "AndroidManifest.xml" };
			ShellUtil.CommandResult nameResult = ShellUtil
	                    .execCommand(nameCommand);
			if (!nameResult.isCommandSucceeded()) {
				logger.info("get launcherable-activity failed");
			}
			String[] results = nameResult.getResultMsg().split(
	                    apkFile.getPackageName());
			for (int i = 0; i < results.length; i++) {
				if (results[i].contains("android.intent.action.MAIN")) {
					String[] ssx = results[i].split("\n");
					String s = ssx[0].trim().substring(0, ssx[0].length() - 2);
					apkFile.setActivityName(apkFile.getPackageName() + s);
				}
			}
		}
		return apkFile;
	}

	private static String generateIconFile(String apkFilePath,
			String iconFilePath, String iconFileRealPath) {
		if (StringUtil.isEmpty(iconFilePath)) {
			return "";
		}

		String[] dumpCommand = {
				"sh",
				"-c",
				"unzip -p " + apkFilePath + " " + iconFilePath + " > "
						+ iconFileRealPath };
		ShellUtil.execCommand(dumpCommand);
		return iconFileRealPath;
	}

	private static Task decodeTask(String parameter)
			throws UnsupportedEncodingException {
		// parse parameters
		String decodedParams = new String(Base64.decodeBase64(parameter
				.getBytes(GlobalConstants.DEFAULT_ENCODE)),
				GlobalConstants.DEFAULT_ENCODE);
		logger.debug("recv parameter string: {}", decodedParams);

		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
				.create();
		Task task = gson.fromJson(decodedParams, new TypeToken<Task>() {
		}.getType());

		logger.info("recv parameter obj: {}", task);
		return task;
	}

	private static String getWorkDir(String taskId) {
		// set working dir
		String rootPath = GlobalConfig.getInstance().getWorkDir() + taskId;
		File rootDir = new File(rootPath);
		if (rootDir.exists()) {
			rootDir.delete();
		}
		rootDir.mkdirs();

		if (!rootPath.endsWith(File.separator)) {
			rootPath += File.separator;
		}
		return rootPath;
	}

	private void startCompatibilityTest(String parameter) throws BaseException,
			UnsupportedEncodingException {

		Task task = decodeTask(parameter);
		API_URL = task.getApi_url();
		STORAGE_URL = task.getStorage_url();
		rootPath = getWorkDir(task.getTaskId());
		
		String fileName = "Application-Test"; // FileUtil.gfb(task.getAppUrl());
		String apkLocalFilePath = task.getAppUrl();
		long fileSize = 0l;
		ApkFile apkFile = parseApkFile(apkLocalFilePath);
		apkFile.setLocalFilePath(apkLocalFilePath);
		apkFile.setSize(fileSize);
		if (StringUtil.isEmpty(apkFile.getName())) {
			apkFile.setName(fileName); // set file name as default app name if
										// it cannot be parsed.
		}

		logger.info(apkFile.toString());
		ShellUtil.killAdbServer();
//		ShellUtil.	setJavaEnvCmdExc();


		// get apk icon file
		String iconFileRealPath = rootPath + GlobalConstants.APP_ICON_NAME;
		apkFile.setIconLocalFilePath(generateIconFile(apkLocalFilePath,
				apkFile.getIcon(), iconFileRealPath));
		task.setApkFile(apkFile);

		logger.info("task.getDevices().size:" + task.getDevices().size());
//		ArrayList<CompatibilityTestExecutor> threads = new ArrayList<CompatibilityTestExecutor>();
		// perform tasks
		for (int i = 0; i < task.getDevices().size(); i++) {
			Device device = task.getDevices().get(i);
			concurrentCount.incrementAndGet();
			String deviceRootPath = rootPath + device.getDeviceId()
					+ File.separator;
			logger.info("zyf100:concurrentCount.get():" + concurrentCount.get());
			CompatibilityTestExecutor thread = new CompatibilityTestExecutor(
					task.getTaskId(), deviceRootPath, concurrentCount,
					task.getApkFile(), device, task.getToken(),task);
			thread.start();
//			threads.add(thread);

			try {
				thread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}

			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			} // short delay to avoid adb concurrent connect issue.
		}
		logger.info(">> task done >> {}", task);
	
		System.exit(0);
	}


	/*private void startCalabashTest(String parameter) throws BaseException,
			UnsupportedEncodingException, InterruptedException {

		Task task = decodeTask(parameter);
		rootPath = getWorkDir(task.getTaskId());

		String zipFileName = "calabash-test.zip";
		String zipLocalFilePath = rootPath + zipFileName;

		long fileSize = FileUtil.downloadFile(zipLocalFilePath,
				task.getScriptUrl());
		// let task executor handle it later.
		if (fileSize < 1024) {
			logger.warn(
					">> downloaded script file is not correct, local file [{}], remote url [{}]",
					zipLocalFilePath, task.getScriptUrl());
		}

		String[] command = { "unzip", zipLocalFilePath, "-d", rootPath };
		ShellUtil.CommandResult commandResult = ShellUtil.execCommand(command);
		if (!commandResult.isCommandSucceeded()) {
			logger.error("parse zip file error! {}", zipLocalFilePath);
		}

		String featurePath = null;
		String debugKeyPath = null;
		File rootDir = new File(rootPath);

		for (File file : rootDir.listFiles()) {
			if (file.isDirectory()
					&& file.getName().equals(
							GlobalConstants.KEY_AUTOMATION_FEATURES_NAME)) {
				featurePath = file.getParent();
				logger.info("FeatureParentPath: {}", featurePath);
			}

			if (file.getName().equals("debug.keystore")) {
				debugKeyPath = file.getParent();
				logger.info("has customized debug key: {}",
						file.getAbsolutePath());
			}

			if (!StringUtil.isEmpty(featurePath)
					&& !StringUtil.isEmpty(debugKeyPath)) {
				break; // stop check immediately if both conditions meet.
			}
		}

		if (!StringUtil.isEmpty(featurePath)
				&& !featurePath.endsWith(File.separator)) {
			featurePath += File.separator;
		}

		// download apk file
		String apkFileName = "Application-Test";
		String apkLocalFilePath = rootPath + task.getTaskId() + "-test.apk";

		File file = new File(apkLocalFilePath);
		if (file.exists()) {
			file.delete();
		}

		fileSize = FileUtil.downloadFile(apkLocalFilePath, task.getAppUrl());
		// let task executor handle it later.
		if (fileSize < 1024) {
			logger.warn(
					">> downloaded file is not correct, local file [{}], remote url [{}]",
					apkLocalFilePath, task.getAppUrl());
		}

		// parse apk file
		ApkFile apkFile = parseApkFile(apkLocalFilePath);
		apkFile.setLocalFilePath(apkLocalFilePath);
		apkFile.setSize(fileSize);
		if (StringUtil.isEmpty(apkFile.getName())) {
			apkFile.setName(apkFileName); // set file name as default app name
											// if it cannot be parsed.
		}
		logger.info(apkFile.toString());

		// get apk icon file
		String iconFileRealPath = rootPath + GlobalConstants.APP_ICON_NAME;
		apkFile.setIconLocalFilePath(generateIconFile(apkLocalFilePath,
				apkFile.getIcon(), iconFileRealPath));
		task.setApkFile(apkFile);

		// if do not have debug key then resign apk
		String tmpSubCommand = "";
		if (!StringUtil.isEmpty(debugKeyPath)) {
			tmpSubCommand = " cd " + debugKeyPath + "; ";
		}

		String[] resignCmd = { "sh", "-c",
				tmpSubCommand + "calabash-android resign " + apkLocalFilePath };

		ShellUtil.CommandResult resignResult = ShellUtil.execCommand(resignCmd);
		if (!resignResult.isCommandSucceeded()) {
			logger.warn("resign apk file error! apk file: {}", apkLocalFilePath);
		}

		// perform tasks
		for (Device device : task.getDevices()) {
			concurrentCount.incrementAndGet();
			String deviceRootPath = rootPath + device.getDeviceId()
					+ File.separator;
			new CalabashTestExecutor(task.getTaskId(), deviceRootPath,
					concurrentCount, apkFile, device, task.getToken(),
					featurePath).start();
			Thread.sleep(5000); // short delay to avoid adb concurrent connect  issue.
		}

		// waiting for all task finish.
		while (concurrentCount.get() != 0) {
			synchronized (concurrentCount) {

				concurrentCount.wait(5 * 1000L);
			}
		}

		logger.info(">> task done >> {}", task);
		try {
			FileUtil.deleteDir(rootDir);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	private void startLettuceTest(String parameter) throws BaseException,
			UnsupportedEncodingException, InterruptedException {

		Task task = decodeTask(parameter);
		rootPath = getWorkDir(task.getTaskId());

		String zipFileName = "lettuce-test.zip";
		String zipLocalFilePath = rootPath + zipFileName;

		long fileSize = FileUtil.downloadFile(zipLocalFilePath,
				task.getScriptUrl());
		// let task executor handle it later.
		if (fileSize < 1024) {
			logger.warn(
					">> downloaded script file is not correct, local file [{}], remote url [{}]",
					zipLocalFilePath, task.getScriptUrl());
		}

		String[] command = { "unzip", zipLocalFilePath, "-d", rootPath };
		ShellUtil.CommandResult commandResult = ShellUtil.execCommand(command);
		if (!commandResult.isCommandSucceeded()) {
			logger.error("parse zip file error! {}", zipLocalFilePath);
		}

		String featurePath = null;
		File rootDir = new File(rootPath);

		for (File file : rootDir.listFiles()) {
			if (file.isDirectory()
					&& file.getName().equals(
							GlobalConstants.KEY_AUTOMATION_FEATURES_NAME)) {
				featurePath = file.getParent();
				logger.info("FeatureParentPath: {}", featurePath);
				break;
			}
		}

		if (!StringUtil.isEmpty(featurePath)
				&& !featurePath.endsWith(File.separator)) {
			featurePath += File.separator;
		}

		// download apk file
		String apkFileName = "Application-Test";
		String apkLocalFilePath = rootPath + task.getTaskId() + "-test.apk";

		File file = new File(apkLocalFilePath);
		if (file.exists()) {
			file.delete();
		}

		fileSize = FileUtil.downloadFile(apkLocalFilePath, task.getAppUrl());
		// let task executor handle it later.
		if (fileSize < 1024) {
			logger.warn(
					">> downloaded file is not correct, local file [{}], remote url [{}]",
					apkLocalFilePath, task.getAppUrl());
		}

		// parse apk file
		ApkFile apkFile = parseApkFile(apkLocalFilePath);
		apkFile.setLocalFilePath(apkLocalFilePath);
		apkFile.setSize(fileSize);
		if (StringUtil.isEmpty(apkFile.getName())) {
			apkFile.setName(apkFileName); // set file name as default app name
											// if it cannot be parsed.
		}
		logger.info(apkFile.toString());

		// get apk icon file
		String iconFileRealPath = rootPath + GlobalConstants.APP_ICON_NAME;
		apkFile.setIconLocalFilePath(generateIconFile(apkLocalFilePath,
				apkFile.getIcon(), iconFileRealPath));
		task.setApkFile(apkFile);

		// perform tasks
		for (Device device : task.getDevices()) {
			concurrentCount.incrementAndGet();
			String deviceRootPath = rootPath + device.getDeviceId()
					+ File.separator;
			new LettuceTestExecutor(task.getTaskId(), deviceRootPath,
					concurrentCount, apkFile, device, task.getToken(),
					featurePath).start();
			Thread.sleep(5000); // short delay to avoid adb concurrent connect
								// issue.
		}

		// waiting for all task finish.
		while (concurrentCount.get() != 0) {
			synchronized (concurrentCount) {
				concurrentCount.wait(5 * 1000L);
			}
		}

		logger.info(">> task done >> {}", task);
		try {
			FileUtil.deleteDir(rootDir);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	private void startBackUpOrRestore(String type, String params)
			throws BaseException, UnsupportedEncodingException,
			InterruptedException {
		// parse parameters
		String decodedParams = new String(Base64.decodeBase64(params
				.getBytes(GlobalConstants.DEFAULT_ENCODE)),
				GlobalConstants.DEFAULT_ENCODE);
		logger.debug("recv parameter string: {}", decodedParams);

		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
				.create();
		BackupTask task = gson.fromJson(decodedParams,
				new TypeToken<BackupTask>() {
				}.getType());

		logger.info("recv parameter obj: {}", task);

		// set working dir
		rootPath = GlobalConfig.getInstance().getBackUpDir();
		File dir = new File(rootPath);
		if (!dir.exists()) {
			dir.mkdirs();
		}

		if (!rootPath.endsWith(File.separator)) {
			rootPath += File.separator;
		}

		// perform tasks
		Device device = task.getDevices();
		String deviceRootPath = rootPath + device.getSerialNumber()
				+ File.separator;
		new DeviceDataBackupExecutor(type, task.getTaskId(), deviceRootPath,
				device, task.getToken()).start();

		logger.info(">> task done >> {}", task);
	}*/
}
